//
//  LBXDownLoadManager.m
//  LBXKit
//
//  Created by lbx on 2017/11/2.
//  Copyright © 2017年 lbx. All rights reserved.
//

#import "LBXDownLoadManager.h"
#import "NSURLSessionTask+LBXDownLoadItem.h"
#import <LBXFileHelper.h>
#import "LBXDownLoadOperation.h"
#import <CommonCrypto/CommonDigest.h>

//不监听网络
//#define DisableListenNet

#pragma mark- 下载管理

@interface LBXDownLoadManager()<NSURLSessionDownloadDelegate>

//数据库名称,存储在document目录
@property (nonatomic, copy) NSString *realmName;

@property (nonatomic, strong)  NSMutableArray<LBXDownLoadItem*> *downLoadItems;

@property (nonatomic, strong)  NSMutableArray<NSString*> *hasDownLoadItems;

@property (nonatomic, strong) NSURLSessionConfiguration *config;

@property (nonatomic, strong) NSURLSession *session;

@property (nonatomic, assign) BOOL availableToastShow;

//存储最大优先级
@property (nonatomic, assign) NSInteger maxPriorityLevel;

@property (nonatomic, copy) NSString *itemStoreDir;

@end

@implementation LBXDownLoadManager

+ (instancetype)sharedManager
{
    static LBXDownLoadManager * _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[[self class]  alloc] init];
        [_sharedInstance initParameter];
    });
    return _sharedInstance;
}

- (NSString*)itemStoreDir
{
    if (!_itemStoreDir) {
        
        _itemStoreDir = [[LBXFileHelper documentDir]stringByAppendingPathComponent:@"LBXDownLoad"];
        _itemStoreDir = [_itemStoreDir stringByAppendingPathComponent:@"ItemInfo"];
        [LBXFileHelper createFolder:_itemStoreDir];
    }
    return _itemStoreDir;
}

- (void)startNet
{
    //在ready状态下载
    if ( self.downLoadItems.count > 0 ) {
        
        //是否已经存在在下载的项目
        BOOL exitRunning = NO;
        for (LBXDownLoadItem *item in self.downLoadItems) {
            
            if (item.status == LBXDownloadStatus_Running) {
                exitRunning = YES;
                break;
            }
        }
        
        if (!exitRunning) {
            
            for (LBXDownLoadItem *item in self.downLoadItems) {
                if (item.status == LBXDownloadStatus_Readying || item.status == LBXDownloadStatus_Suspended ) {
                    [self startWithItem:item];
                    break;
                }
            }
        }
    }
}

- (NSMutableArray*)downLoadItems
{
    if (!_downLoadItems) {
        _downLoadItems = [NSMutableArray array];
        NSArray *items = [self loadItems];
        if (items) {
            for (int i = 0; i < items.count; i++) {
                
                LBXDownLoadItem *item = [LBXDownLoadItem itemFromSandBoxWithRemoteURL:items[i]];
                if (item) {
                    [_downLoadItems addObject:item];
                    
//                    __weak typeof(self) weakSelf = self;
//                    item.onStatusChanged = ^(LBXDownLoadItem *item) {
//                        if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(LBXDownLoadStatus:)]) {
//                            [weakSelf.delegate LBXDownLoadStatus:item];
//                        }
//                    };
//
//                    item.onProgressChanged = ^(LBXDownLoadItem *item) {
//                        if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(LBXDownLoadProgress:)]) {
//                            [weakSelf.delegate LBXDownLoadProgress:item];
//                        }
//                    };
                    
                }
            }
        }
    }
    
    return _downLoadItems;
}

- (NSArray*)loadItems
{
    NSString *itemPath = self.itemStoreDir;
        
    itemPath = [itemPath stringByAppendingPathComponent:@"items"];
    
    if ([LBXFileHelper fileExistsAtPath:itemPath]) {
        
        NSData *data = [NSData dataWithContentsOfFile:itemPath];
        
        if (data) {
            NSArray *items = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            return items;
        }
    }
    return nil;
}

- (void)storeItems
{
    if (_downLoadItems) {
        
        @synchronized (self) {
            
            //只存url地址
            NSString *itemPath = self.itemStoreDir;            
            itemPath = [itemPath stringByAppendingPathComponent:@"items"];
            
            NSMutableArray *array = [NSMutableArray array];
            for (int i = 0; i < self.downLoadItems.count; i++) {
                
                NSString *url = self.downLoadItems[i].remoteURL;
                
                [array addObject:url];
            }
                        
            NSData *items = [NSKeyedArchiver archivedDataWithRootObject:array];

            if (items) {
                
                [LBXFileHelper deleteFolderPath:itemPath];
                [items writeToFile:itemPath atomically:YES];
            }
        }
    }
}

- (NSURLSessionConfiguration*)config
{
    if (!_config) {
     
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        
        config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"LBXDownloadIdentifier"];
        
        NSLog(@"%lu",(unsigned long)config.networkServiceType);
        
        /*
         如果不设置，程序进入后台后，仍然下载，但是再次进入前台则不会回调下载进度(控制台报错 BackgroundSession <D10B56FE-44C8-459C-8DA1-CBC25E5A610C> connection to background transfer daemon interrupted)，只有下载完成时回调一次
         添加下面设置，进入前台控制台仍然报错(BackgroundSession <D10B56FE-44C8-459C-8DA1-CBC25E5A610C> connection to background transfer daemon interrupted),但是可以收到下载进度的回调
         */
        config.networkServiceType = NSURLNetworkServiceTypeBackground;
        
//        //也可以设置request里面的header
//        config.HTTPAdditionalHeaders = @{@"Accept": @"application/json",
//                                                        @"Accept-Language": @"en",
//                                                        @"Authorization": auth,
//                                                        @"User-Agent": userAgent};
//        config.HTTPMaximumConnectionsPerHost = 8; //连接到特定主机的数量
//        config.timeoutIntervalForRequest = 30; //超时时间
        config.allowsCellularAccess = self.allowsCellularAccess;  //允许蜂窝访问；
        config.discretionary = YES;  //在后台系统自行决定性能
//        config.sessionSendsLaunchEvents = NO; //一个新的属性，该属性指定该会话是否应该从后台启动
        
        _config = config;
    }
    return _config;
}

- (void)initParameter
{
    self.availableToastShow = YES;
    self.maxPriorityLevel = 0;
    self.maxConcurrentCount = 5;
    self.allowsCellularAccess = YES;
}

- (NSURLSession*)session
{
    if (!_session) {
        
        self.config.HTTPMaximumConnectionsPerHost = self.maxConcurrentCount;
        _session = [NSURLSession sessionWithConfiguration:self.config
                                                     delegate:self
                                                delegateQueue:nil];
    }
    return _session;
}

//+ (void)addRealmItem:()

- (BOOL)availabelLeftSpace:(LBXDownLoadItem*)item
{
    //判断空间是否够了,保留200MB空余
    if ( (item.fileSize + 200*1024*1024) > ([LBXFileHelper getDiskFreeSize])) {
        
//        [NSObject showToastWithMessage:@" 您手机的空间不足，请清理后重试 "];
        return NO;
    }
    return YES;
}

#pragma mark- 下载状态管理

- (void)showToastWithMessage:(NSString*)message
{
    if (_availableToastShow) {
        self.availableToastShow = NO;
        
//        [NSObject showToastWithMessage:message];
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self.availableToastShow = YES;
        });
    }
}

// 开始下载
- (void)startWithItem:(LBXDownLoadItem*)item
{
    if ( !item ) {
        return;
    }
    
    //增加同时下载个数判断，超过指定同时下载数量，不执行
    NSInteger curMaxNum = 0;

    for (LBXDownLoadItem *_item in [LBXDownLoadManager sharedManager].downLoadItems) {
        if (_item.status == LBXDownloadStatus_Running) {
            curMaxNum++;
            if (curMaxNum >= self.maxConcurrentCount) {
                break;
            }
        }
    }
    [self addItem:item];

    if (curMaxNum >= self.maxConcurrentCount) {
        //等待下载
        item.status = LBXDownloadStatus_Readying;
        return;
    }
    
//    if (self.networkState == 1) {
//        [self showToastWithMessage:@"您目前在非Wi-Fi状态下，请连接Wi-Fi后重试"];
//        return;
//    }
    
    if (![self availabelLeftSpace:item]) {
        return;
    }
    
    self.maxPriorityLevel++;
    item.priorityLevel = self.maxPriorityLevel;
    
    item.status = LBXDownloadStatus_Running;
    if (item.op == nil)
    {
        item.op = [[LBXDownLoadOperation alloc]initWithItem:item session:self.session];
        [item.op start];
    }
    else
    {
       [item.op resume];
    }
}

//下载完成一个后，自动判断是否需要下载新的资源
- (void)autoDownNextItem
{
    //按顺序判断，是否有 readying状态，有的话，则开始执行一个下载
    for (int i = 0; i < self.downLoadItems.count; i++) {

        if (self.downLoadItems[i].status == LBXDownloadStatus_Readying) {

            [self startWithItem:self.downLoadItems[i]];
            break;
        }
    }
}

- (void)addItem:(LBXDownLoadItem*)item
{
    if (!item || item.remoteURL == nil ) {
        return;
    }
    if (![self.downLoadItems containsObject:item]) {
        //判断下载地址是否一致，如果一样也不能添加下载任务
        __block BOOL isSameRemoteURL = NO;
        [self.downLoadItems enumerateObjectsUsingBlock:^(LBXDownLoadItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([item.remoteURL isEqualToString:obj.remoteURL]) {
                isSameRemoteURL = YES;
                *stop = YES;
            }
        }];
  
        if (!isSameRemoteURL) {
            
            @synchronized (self) {
                [self.downLoadItems addObject:item];
            }
            [self storeItems];
            
//            __weak typeof(self) weakSelf = self;
//            item.onStatusChanged = ^(LBXDownLoadItem *item) {
//                if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(LBXDownLoadStatus:)]) {
//
//                    [weakSelf.delegate LBXDownLoadStatus:item];
//                }
//            };
//
//            item.onProgressChanged = ^(LBXDownLoadItem *item) {
//
//                if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(LBXDownLoadProgress:)]) {
//
//                    [weakSelf.delegate LBXDownLoadProgress:item];
//                }
//            };
        }
    }
}

- (void)startOrSuspendItem:(LBXDownLoadItem*)item
{
    switch (item.status) {
        case LBXDownloadStatus_Completed:
            break;
        case LBXDownloadStatus_Running:
            [self suspendWithItem:item];
            break;
        default:
            [self startWithItem:item];
            break;
    }
}

- (void)suspendWithItem:(LBXDownLoadItem*)item
{
    if (item.op) {
        [item.op suspend];
    }else
    {
        item.status = LBXDownloadStatus_Suspended;
    }
}

- (void)cancelWithItem:(LBXDownLoadItem*)item
{
    [self delWithItem:item];
}

- (void)delWithItem:(LBXDownLoadItem*)item
{
    if (!item) {
        return;
    }
    
    item.onStatusChanged = nil;
    item.onProgressChanged = nil;
    
    if (item.op) {
        [item.op cancel];
    }
    
    [item deleteItem];
    
    BOOL exist = NO;
    @synchronized (self) {
        if ([self.downLoadItems containsObject:item]) {
            [self.downLoadItems removeObject:item];
            exist = YES;
        }
    }
    if (exist) {
        [self storeItems];
    }
}

- (void)resumeWithItem:(LBXDownLoadItem*)item
{
    [self startWithItem:item];
}

//暂停所有
- (void)suspendAll
{
    for (LBXDownLoadItem *item in self.downLoadItems) {
        [self suspendWithItem:item];
    }
}

- (LBXDownLoadItem*)maxPriorityLevelItem
{
    if (self.downLoadItems.count == 0) {
        return nil;
    }
    LBXDownLoadItem *maxPriorityItem = nil;
    for (LBXDownLoadItem *item in self.downLoadItems) {
        if (item.status != LBXDownloadStatus_Running && item.status != LBXDownloadStatus_Completed ) {
            if (maxPriorityItem == nil || item.priorityLevel > maxPriorityItem.priorityLevel ) {
                maxPriorityItem = item;
            }
        }
    }
    return maxPriorityItem;
}

//全部开始，只是指定个数开始
- (void)startAll
{
    //找出优先级最高的一个
    LBXDownLoadItem *priorityItem = [self maxPriorityLevelItem];
    if (priorityItem) {
        [self startWithItem:priorityItem];
    }
   
    for (LBXDownLoadItem *item in self.downLoadItems) {
        if (item.status != LBXDownloadStatus_Running) {
            [self startWithItem:item];
        }
    }
}

//取消所有，应该要删除相应记录?
- (void)cancelAll
{
    for (LBXDownLoadItem *item in self.downLoadItems) {
        [self cancelWithItem:item];
    }
}

- (void)resumeAll
{
    [self startAll];
}

- (void)clearAllBlock
{
    for (LBXDownLoadItem *item in self.downLoadItems)
    {
        item.onStatusChanged = nil;
        item.onProgressChanged = nil;
    }
}

//检查item是否真正下载完成
- (BOOL)realFinishWithItem:(LBXDownLoadItem*)item
{
    if (item.status == LBXDownloadStatus_Completed) {
        
        NSString *filePath = item.localFilePath;
        
        if ( [LBXFileHelper fileExistsAtPath:filePath] ) {
                     
            return YES;
        }
        else
        {
            if (item.op) {
                [item.op cancel];
            }
            item.resumeData = nil;
            item.status = LBXDownloadStatus_Failed;
        }
    }
    return NO;
}

//移除已经下载完成的item
- (void)clearFinishItem
{
    NSMutableIndexSet *mutableIndexSet = [[NSMutableIndexSet alloc]init];
    @synchronized(self)
    {
        for (int i = 0; i < self.downLoadItems.count; i++)
        {
            LBXDownLoadItem *item = self.downLoadItems[i];
            if ( [self realFinishWithItem:item] ) {
                [mutableIndexSet addIndex:i];
                [self.hasDownLoadItems addObject:item.remoteURL];
                
                item.onStatusChanged = nil;
                item.onProgressChanged = nil;
            }
        }
        if (mutableIndexSet.count > 0) {
            
            [self.downLoadItems removeObjectsAtIndexes:mutableIndexSet];
        }
    }
    
    if (mutableIndexSet.count > 0) {
        //存储待下载
        [self storeItems];
        //存储下载成功的url地址
        [self storeHasDownLoadItems];
    }
}

- (void)refreshDownLoadStatus
{
    [self clearFinishItem];
    
//    if (self.refreshDownLoadBlock) {
//        dispatch_async(dispatch_get_main_queue(), ^{
//            self.refreshDownLoadBlock();
//        });
//    }
}


#pragma mark - NSURLSessionDownloadDelegate
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location
{
    NSLog(@"location url:%@",location);
//    file:///Users/lbx/Library/Developer/CoreSimulator/Devices/A46CC282-79F3-4E98-9903-4CD0FCBE8E9F/data/Containers/Data/Application/CAECD431-6BE8-47A7-95BF-A0DEA251169F/Library/Caches/com.apple.nsurlsessiond/Downloads/com.yunqueyi.Doctor/CFNetworkDownload_rIGk7q.tmp
    
    LBXDownLoadItem *item = downloadTask.lbx_downLoadItem;
    
    if (item == nil) {
        //APP启动时，回调的下载完成的文件
        
        NSLog(@"item is nil");
        
        //TODO ：读取所有缓存文件，判断是否存在，存在的则进行下载完成相关工作
        NSArray *array = [self.downLoadItems copy];
        
        for (LBXDownLoadItem *aItem in array) {
            
            if (aItem.taskIdentifier == downloadTask.taskIdentifier) {
                item = aItem;
                break;
            }
        }

        NSLog(@"%ld,%@",downloadTask.taskIdentifier,downloadTask.taskDescription);
        
        if (!item) {
            return;

        }
    }

    NSString *filePath = item.localFilePath;
    
    BOOL success = NO;
    
    if (filePath) {
        NSURL *toURL = [NSURL fileURLWithPath:filePath];
        
        success = [self moveFromURL:location toURL:toURL];
        
        item.status = success ? LBXDownloadStatus_Completed: LBXDownloadStatus_Failed;

        //先清理列表数据，再更新状态，否则UI界面数据不同步，会异常
        if (success) {
            //刷新状态
            [self refreshDownLoadStatus];
            
            if (_delegate && [_delegate respondsToSelector:@selector(LBXDownLoadSucess:)]) {
                [_delegate LBXDownLoadSucess:item];
            }
        }
        else
        {
            //存储失败
            item.resumeData = nil;
        }
       
    }
    else
    {
        item.status = LBXDownloadStatus_Failed;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self autoDownNextItem];
    });
}


// app 在前台时不会回调该方法
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
    
}


- (BOOL)moveFromURL:(NSURL*)srcURL toURL:(NSURL*)dstURL
{
    if (![LBXFileHelper fileExistsAtPath:srcURL.path]) {
        NSLog(@"moveFromURL 原文件不存在");
        return NO;
    }
    
    if ( [LBXFileHelper fileExistsAtPath:dstURL.path] ) {
        NSLog(@"源文件已经存在");
        return YES;
    }
    
    
    //原文件与目的文件是否大小一致
    
    
    //如果目的路径存储文件，则先删除
    //    [self deleteFileAtPath:dstURL.path];
    
    NSFileManager *manager = [NSFileManager defaultManager];
    NSError *error = nil;
    //        BOOL success = [manager moveItemAtURL:srcURL toURL:dstURL error:&error];
    
    NSLog(@"srcPath:%@",srcURL.path);
    NSLog(@"dstPath:%@",dstURL.path);
    
    BOOL success = [manager moveItemAtPath:srcURL.path toPath:dstURL.path error:&error];
    
    if (error) {
        NSLog(@"moveWithURL error:%@",error);
    }
    
    return success;
}

/*
 * 该方法下载成功和失败都会回调，只是失败的是error是有值的，
 * 在下载失败时，error的userinfo属性可以通过NSURLSessionDownloadTaskResumeData
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"error:%@,errorCode:%ld",error,error.code);

    if (error == nil) {
        return;
    }
    
    LBXDownLoadItem *item = task.lbx_downLoadItem;

    
    NSDictionary *userInfo = error.userInfo;
    
    NSData *resumeData = userInfo[@"NSURLSessionDownloadTaskResumeData"];
    if (resumeData)
    {
        //resumeData xml
        //    NSErrorFailingURLStringKey = "http://120.25.226.186:32812/resources/videos/minion_01.mp4";
        //    NSURLErrorBackgroundTaskCancelledReasonKey = 0;
        //    NSURLSessionDownloadTaskResumeData
//        NSLog(@"resumedata len:%ld",resumeData.length);
//        NSString *xml = [[NSString alloc]initWithData:resumeData encoding:NSUTF8StringEncoding];
//        NSLog(@"resumeData xml：%@",xml);
        
        if (item) {
            //在suspend的地方已经获取,但是有可能报错导致的断点信息？
            item.resumeData = resumeData;
            
            item.status = LBXDownloadStatus_Suspended;

            return;
        }
        else if(userInfo[@"NSErrorFailingURLStringKey"])
        {
            //应该APP启动时回调的断点信息
            //TODO:读取所有下载列表，将resumeData 存储到对应item中
        }
        else if(task.taskIdentifier > 0)
        {
            //从item中寻找taskIdentifier相等的
            //应该不会发生，只有在后台下载，下载完毕，没有保存，APP后台删除后，启动时，会抛出一个下载完成的下载地址
        }
        
        return;
    }

    if (item) {
        
//        Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory" UserInfo={NSErrorFailingURLKey=https://1253597694.vod2.myqcloud.com/30b7a892vodgzp1253597694/6c2a9da69031868223043077765/f0.mp4, NSErrorFailingURLStringKey=https://1253597694.vod2.myqcloud.com/30b7a892vodgzp1253597694/6c2a9da69031868223043077765/f0.mp4},errorCode:2
        
        //有时候遇到这种情况，重新点击下载，会仍然报这个错误。测试APP重启一下，一般可以恢复正常。
        
        item.status = LBXDownloadStatus_Failed;
    }
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    
    NSLog(@"totalBytesExpectedToWrite:%lld,totalBytesWritten=%lld",totalBytesExpectedToWrite,totalBytesWritten);

    
    LBXDownLoadItem *item = downloadTask.lbx_downLoadItem;
    
    
    if (item == nil) {
        //APP启动时，回调的下载完成的文件
        
        NSLog(@"item is nil");
        
        //TODO ：读取所有缓存文件，判断是否存在，存在的则进行下载完成相关工作
        NSArray *array = [self.downLoadItems copy];
        
        for (LBXDownLoadItem *aItem in array) {
            
            if (aItem.taskIdentifier == downloadTask.taskIdentifier) {
                item = aItem;
                break;
            }
        }
      
    }
    
    if (item != nil) {
        
        item.fileSize = totalBytesExpectedToWrite;
        item.downSize = totalBytesWritten;

        return;
    }
    
    //应该是恢复下载的情况，这里如何处理？
    [downloadTask cancel];
}

//恢复下载?
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                    expectedTotalBytes:(int64_t)expectedTotalBytes
{
    NSLog(@"恢复下载 totalBytesWritten:%lld,totalBytesExpectedToWrite=%lld",fileOffset,expectedTotalBytes);
    
    LBXDownLoadItem *item = downloadTask.lbx_downLoadItem;
    
    if (item) {
        
//        item.fileSize = expectedTotalBytes;
//        item.downSize = fileOffset;
        
        //恢复下，计算下载进度
//        LBXDownLoadProgress *progress = item.dbProgress;
//        progress.totalBytesWritten = fileOffset;
//        progress.totalBytesExpectedToWrite = expectedTotalBytes;
////        progress.preWrittenTime = [NSDate date];
////        progress.speed = 0;
////        progress.remainingTime = 60*60*24;
//
//        item.dbProgress = progress;
    }
}

#pragma mark- 工具

//计算时间差
- (NSTimeInterval)diffWitdNewDate:(NSDate*)newDate oldDate:(NSDate*)oldDate
{
    // 时间2与时间1之间的时间差（秒）
    NSTimeInterval intervalTime = [newDate timeIntervalSinceReferenceDate] - [oldDate timeIntervalSinceReferenceDate];
    
//    NSInteger seconds = intervalTime % 60;
//    NSInteger minutes = (intervalTime / 60) % 60;
//    NSInteger hours = (intervalTime / 3600);
//    NSInteger days = intervalTime/60/60/24;
//    NSInteger month = intervalTime/60/60/24/12;
//    NSInteger years = intervalTime/60/60/24/365;
    
    return intervalTime;
}

//计算速度,kb/s
- (int64_t)speedWithDidWriteData:(int64_t)bytesWritten preDate:(NSDate*)preDate nowDate:(NSDate*)nowDate
{
    NSTimeInterval intervalTime = [nowDate timeIntervalSinceReferenceDate] - [preDate timeIntervalSinceReferenceDate];
    
    int64_t kb = bytesWritten / 1024;
    
    return kb/intervalTime;
}

//剩余时间，单位s
- (int64_t)remainTimeWithSpeed:(float)speed
             totalBytesWritten:(int64_t)totalBytesWritten
     totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    //剩余字节数
    int64_t remainBytes = totalBytesExpectedToWrite - totalBytesWritten;
    if ( remainBytes <= 0 )
    {
        //下载完成
        return 0;
    }
    
    if ( speed <= 0 )
    {
        //一天时间
        return 60*60*24;
    }
    return remainBytes / speed;
}

#pragma mark- 已下载文件管理
- (NSString*)localFilePathWithRemoteURL:(NSString*)remoteURL
{
    LBXDownLoadItem *item = [[LBXDownLoadItem alloc]init];
    item.remoteURL = remoteURL;
    
    if ( [item fileCacheExist] ) {
        return item.localFilePath;
    }    
    return nil;
}


- (void)deleteAllDownedFiles
{
    @synchronized (self) {
        for (int i = 0; i < self.hasDownLoadItems.count; i++) {
            
            NSString *remoteURL = self.hasDownLoadItems[i];
            
            NSString *filePath = [self localFilePathWithRemoteURL:remoteURL];
            [LBXFileHelper deleteFileAtPath:filePath];
        }
        [self.hasDownLoadItems removeAllObjects];
    }
    
    [self storeHasDownLoadItems];
}

//删除已经下载的文件
- (void)deleteFileWithRemoteURL:(NSString*)remoteURL
{
    if (!remoteURL) {
        return;
    }
    
    //删除记录
    @synchronized (self) {
        
        if ([self.hasDownLoadItems containsObject:remoteURL])
        {
            [self.hasDownLoadItems removeObject:remoteURL];
            [self storeHasDownLoadItems];
        }
    }
    
    //删除实际文件
    NSString *filePath = [self localFilePathWithRemoteURL:remoteURL];
    [LBXFileHelper deleteFileAtPath:filePath];
}

- (void)storeHasDownLoadItems
{
    @synchronized (self) {
        
        //只存url地址
        NSString *itemPath = self.itemStoreDir;
        itemPath = [itemPath stringByAppendingPathComponent:@"itemsDowned"];
                    
        NSData *items = [NSKeyedArchiver archivedDataWithRootObject:self.hasDownLoadItems];

        if (items) {
            [LBXFileHelper deleteFolderPath:itemPath];
            [items writeToFile:itemPath atomically:YES];
        }
    }
}

- (NSMutableArray*)hasDownLoadItems
{
    if ( !_hasDownLoadItems ) {
        @synchronized ( self ) {
            
            _hasDownLoadItems = [NSMutableArray array];

            NSString *itemPath = self.itemStoreDir;
                
            itemPath = [itemPath stringByAppendingPathComponent:@"itemsDowned"];
            
            if ([LBXFileHelper fileExistsAtPath:itemPath]) {
                
                NSData *data = [NSData dataWithContentsOfFile:itemPath];
                
                if (data) {
                    NSArray *items = [NSKeyedUnarchiver unarchiveObjectWithData:data];

                    if (items ) {
                        [_hasDownLoadItems addObjectsFromArray:items];
                    }
                }
            }
        }
        
        //删除已经不存在的文件记录
        [self checkHasDownLoadItems];
    }
    return _hasDownLoadItems;
}

//检查已下载文件记录，如果实际不存在，则删除记录
- (void)checkHasDownLoadItems
{
    NSMutableIndexSet *mutableIndexSet = [[NSMutableIndexSet alloc]init];

    @synchronized (self) {
        
        for (int i = 0; i < self.hasDownLoadItems.count; i++) {
            
            NSString *url = self.hasDownLoadItems[i];
            
            NSString *localFilePath = [self localFilePathWithRemoteURL:url];
            if (![LBXFileHelper fileExistsAtPath:localFilePath]) {
                [mutableIndexSet addIndex:i];
            }
        }
        if (mutableIndexSet.count > 0) {
            [self.hasDownLoadItems removeObjectsAtIndexes:mutableIndexSet];
        }
    }
    
    if (mutableIndexSet.count > 0) {
        [self storeHasDownLoadItems];
    }
}

@end
